<?php
declare (strict_types=1);

namespace app\admin\logic\user;

use app\admin\event\subscribes\user\Account as AccountSubscribe;
use app\admin\model\user\Account as AccountModel;
use app\admin\model\user\GroupAccess;
use app\common\exception\LogicException;
use app\school\logic\school\admin\School;
use Exception;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\{Db, Event};
use think\Model;
use think\Paginator;

class Account extends AccountModel
{
    /**
     * 用户登录
     * Author   亓官雨树<lucky.max@foxmail.com>
     * Date 2020-03-12
     */
    public function login(array $data)
    {
        // 验证数据
        $this->getValidate()->scene('login')->failException()->check($data);
        // 用户信息
        $map['user_name|phone'] = $data['user_name'];
        $user                   = $this->where($map)->find();
        // 判断
        if (!$user) {
            throw new LogicException('账号或密码错误', '账号不存在');
        } else {
            $inputPassword = $this->makePassword($data['password'], $user->salt);
            if ($inputPassword != $user->password) {
                throw new LogicException('账号或密码错误', '密码错误');
            }
        }
        // 账号状态是否正常
        $this->checkStatus($user);

        // 是否当前机构的超级管理员
        $user->is_supper_admin = false; // app(School::class)->where('id', $user->mhm_id)->value('admin_user_id') == $user->id;
        // 登录成功
        Event::subscribe(AccountSubscribe::class);
        Event::trigger('UserLogin', $user);

        // 返回值
        return $user;
    }

    /**
     * 检测账号状态
     * Author   Martinsun<syh@sunyonghong.com>
     * Date 2020-03-10
     */
    public function checkStatus(Account $user): void
    {
        if ($user->status === 0) {
            throw new LogicException('账号已被禁止登录', '账号被禁用');
        }
    }

    /**
     * 创建后台用户
     * Author   亓官雨树<lucky.max@foxmail.com>
     * Date 2020-03-12
     *
     * @param array $data [接口传入信息]
     * @return Account $user  [创建的用户信息]
     * @throws Exception
     */
    public function createUser(array $data): self
    {
        // 验证数据
        $this->getValidate()->scene('create')->failException()->check($data);
        $this->startTrans();
        try {
            // 用户信息
            $user = $this::create($data);
            // 创建成功
            if ($user->isEmpty()) throw new LogicException('新建失败');
            // 用户组
            $group = $data['group'] ?? [];
            if (!empty($group)) {
                $ret = GroupAccess::create(['admin_user_id' => $user->getAttr('id'), 'admin_user_group_ids' => $group]);
                if ($ret->isEmpty()) throw new LogicException('新建失败');
            }
            $this->commit();

            return $user;
        } catch (LogicException|Exception $e) {
            $this->rollback();
            throw $e;
        }
    }

    /**
     * 编辑后台用户
     * Author   亓官雨树<lucky.max@foxmail.com>
     * Date 2020-03-12
     *
     * @param array $data [接口传入信息]
     * @return Account $user  [编辑的用户信息]
     * @throws Exception
     */
    public function editUser(array $data): self
    {
        // 验证数据
        $this->getValidate()->scene('edit')->failException()->check($data);
        // 用户信息
        $user = $this->findOrEmpty($data['id']);
        if ($user->isEmpty()) throw new LogicException('用户信息错误');

        $data['password'] && $user->password = $data['password'];
        $user->user_name = $data['user_name'];
        $user->phone     = $data['phone'] ?? '';
        // $user->status    = $data['status'];
        $this->startTrans();
        try {
            // 用户信息
            if (!$user->save()) throw new LogicException('修改失败');
            if (isset($data['group_ids'])) {
                $access = app(GroupAccess::class)->whereAdminUserId($data['id'])->findOrEmpty();
                // 用户组
                $group_ids = $data['group_ids'];
                // 用户组
                if ($access->isEmpty()) {
                    $re2 = GroupAccess::create(['admin_user_id' => $user->id, 'admin_user_group_ids' => $group_ids]);
                    if ($re2->isEmpty()) throw new LogicException('修改失败');
                } else {
                    $access->admin_user_group_ids = $group_ids;
                    if (!$access->save()) throw new LogicException('修改失败');
                }
            }

            $this->commit();
        } catch (LogicException $e) {
            $this->rollback();
            throw new LogicException($e->getMessage());
        } catch (Exception $e) {
            $this->rollback();
            throw $e;
        }

        Event::subscribe(AccountSubscribe::class);
        Event::trigger('UserUpdated', $user);

        // 返回值
        return $user;
    }

    /**
     * 编辑后台用户指定字段
     * Author   亓官雨树<lucky.max@foxmail.com>
     * Date 2020-03-12
     */
    public function editUserField($id, array $data)
    {
        $fields = array_keys($this->getFields());
        $field  = array_keys($data)[0];
        if (!in_array($field, $fields)) {
            throw new LogicException('系统错误');
        }
        // 用户信息
        $user = $this->findOrEmpty($id);
        if ($user->isEmpty()) throw new LogicException('用户信息错误');

        $user->$field = $data[$field];
        if (!$user->save()) throw new LogicException('编辑失败');

        Event::subscribe(AccountSubscribe::class);
        Event::trigger('UserUpdated', $user);

        // 返回值
        return $user;
    }

    /**
     * 删除用户
     * Author: Martinsun <syh@sunyonghong.com>
     * Date: 2020/9/28
     *
     * @param $id
     * @return array|Model|null
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function deleteUser($id)
    {
        Db::startTrans();
        try {
            $user = $this->findOrFail($id);
            if (!$user->force()->delete()) throw new LogicException('删除失败');
            // 删除用户组信息
            $group = app(GroupAccess::class)->whereAdminUserId($id)->findOrFail();
            if (!$group->force()->delete()) throw new LogicException('删除失败');

            Db::commit();
        } catch (LogicException $e) {
            Db::rollback();
            throw new LogicException($e->getMessage());
        }

        // 返回值
        return $user;
    }

    /**
     * 用户列表
     * Author   亓官雨树<lucky.max@foxmail.com>
     * Date 2020-03-13
     */
    public function getUserList(array $map = [], int $group_id = 0): Paginator
    {
        if ($group_id) {
            $like  = ['[' . $group_id . ',%', '%,' . $group_id . ',%', '%,' . $group_id . ']', '[' . $group_id . ']'];
            $ids   = app(GroupAccess::class)->where('admin_user_group_ids', 'like', $like, 'OR')->column('admin_user_id');
            $map[] = ['id', 'IN', $ids];
        }

        $groups = app(Group::class)->getGroupsArr();

        return $this->scope(['excludeAdmin', 'mhm'])->with(['group_ids'])->where($map)->order('update_time', 'DESC')->paginate(static::getListRows())
            ->each(function ($i) use ($groups) {
                $name = '';
                if (is_array($i['group_ids'])) {
                    foreach ($i['group_ids'] as $id) {
                        if (isset($groups[$id])) {
                            $name .= $groups[$id]['title'] . ',';
                        }
                    }
                }
                $i->group = trim($name, ',');
            });
    }

    /**
     * 获取用户的用户组
     * Author   亓官雨树<lucky.max@foxmail.com>
     * Date 2020-03-20
     */
    public function getUserGroups($userId): array
    {
        $user = $this->find($userId);

        return ($user->groupAccess) ? $user->groupAccess->admin_user_group_ids : [];
    }

    /**
     * 设置用户的用户组
     * Author   亓官雨树<lucky.max@foxmail.com>
     * Date 2020-03-20
     */
    public function setUserGroups($userId, $groups)
    {
        $user = $this->find($userId);
        if ($user->groupAccess) {
            $user->groupAccess->admin_user_group_ids = $groups;

            return $user->groupAccess->save();
        }

        return $user->groupAccess()->save(['admin_user_group_ids' => $groups]);
    }

    public function getUserPhone($user_id)
    {
        $user = $this->findOrEmpty($user_id);

        return $user->isEmpty() ? '' : ($user->phone ?: '');
    }
}
